#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ambari_jinja2.testsuite.filters
~~~~~~~~~~~~~~~~~~~~~~~~

Tests for the jinja filters.

:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""

import unittest
from ambari_jinja2.testsuite import JinjaTestCase

from ambari_jinja2 import Markup, Environment

env = Environment()


class FilterTestCase(JinjaTestCase):
  def test_capitalize(self):
    tmpl = env.from_string('{{ "foo bar"|capitalize }}')
    assert tmpl.render() == "Foo bar"

  def test_center(self):
    tmpl = env.from_string('{{ "foo"|center(9) }}')
    assert tmpl.render() == "   foo   "

  def test_default(self):
    tmpl = env.from_string(
      "{{ missing|default('no') }}|{{ false|default('no') }}|"
      "{{ false|default('no', true) }}|{{ given|default('no') }}"
    )
    assert tmpl.render(given="yes") == "no|False|no|yes"

  def test_dictsort(self):
    tmpl = env.from_string(
      "{{ foo|dictsort }}|"
      "{{ foo|dictsort(true) }}|"
      '{{ foo|dictsort(false, "value") }}'
    )
    out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
    assert out == (
      "[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
      "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
      "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]"
    )

  def test_batch(self):
    tmpl = env.from_string("{{ foo|batch(3)|list }}|" "{{ foo|batch(3, 'X')|list }}")
    out = tmpl.render(foo=range(10))
    assert out == (
      "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
      "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]"
    )

  def test_slice(self):
    tmpl = env.from_string("{{ foo|slice(3)|list }}|" '{{ foo|slice(3, "X")|list }}')
    out = tmpl.render(foo=range(10))
    assert out == (
      "[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
      "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]"
    )

  def test_escape(self):
    tmpl = env.from_string("""{{ '<">&'|escape }}""")
    out = tmpl.render()
    assert out == "&lt;&#34;&gt;&amp;"

  def test_striptags(self):
    tmpl = env.from_string("""{{ foo|striptags }}""")
    out = tmpl.render(
      foo='  <p>just a small   \n <a href="#">'
      "example</a> link</p>\n<p>to a webpage</p> "
      "<!-- <p>and some commented stuff</p> -->"
    )
    assert out == "just a small example link to a webpage"

  def test_filesizeformat(self):
    tmpl = env.from_string(
      "{{ 100|filesizeformat }}|"
      "{{ 1000|filesizeformat }}|"
      "{{ 1000000|filesizeformat }}|"
      "{{ 1000000000|filesizeformat }}|"
      "{{ 1000000000000|filesizeformat }}|"
      "{{ 100|filesizeformat(true) }}|"
      "{{ 1000|filesizeformat(true) }}|"
      "{{ 1000000|filesizeformat(true) }}|"
      "{{ 1000000000|filesizeformat(true) }}|"
      "{{ 1000000000000|filesizeformat(true) }}"
    )
    out = tmpl.render()
    assert out == (
      "100 Bytes|1.0 KB|1.0 MB|1.0 GB|1000.0 GB|"
      "100 Bytes|1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB"
    )

  def test_first(self):
    tmpl = env.from_string("{{ foo|first }}")
    out = tmpl.render(foo=range(10))
    assert out == "0"

  def test_float(self):
    tmpl = env.from_string(
      '{{ "42"|float }}|' '{{ "ajsghasjgd"|float }}|' '{{ "32.32"|float }}'
    )
    out = tmpl.render()
    assert out == "42.0|0.0|32.32"

  def test_format(self):
    tmpl = env.from_string("""{{ "%s|%s"|format("a", "b") }}""")
    out = tmpl.render()
    assert out == "a|b"

  def test_indent(self):
    tmpl = env.from_string("{{ foo|indent(2) }}|{{ foo|indent(2, true) }}")
    text = "\n".join([" ".join(["foo", "bar"] * 2)] * 2)
    out = tmpl.render(foo=text)
    assert out == (
      "foo bar foo bar\n  foo bar foo bar|  " "foo bar foo bar\n  foo bar foo bar"
    )

  def test_int(self):
    tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|' '{{ "32.32"|int }}')
    out = tmpl.render()
    assert out == "42|0|32"

  def test_join(self):
    tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
    out = tmpl.render()
    assert out == "1|2|3"

    env2 = Environment(autoescape=True)
    tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
    assert tmpl.render() == "&lt;foo&gt;<span>foo</span>"

  def test_last(self):
    tmpl = env.from_string("""{{ foo|last }}""")
    out = tmpl.render(foo=range(10))
    assert out == "9"

  def test_length(self):
    tmpl = env.from_string("""{{ "hello world"|length }}""")
    out = tmpl.render()
    assert out == "11"

  def test_lower(self):
    tmpl = env.from_string("""{{ "FOO"|lower }}""")
    out = tmpl.render()
    assert out == "foo"

  def test_pprint(self):
    from pprint import pformat

    tmpl = env.from_string("""{{ data|pprint }}""")
    data = range(1000)
    assert tmpl.render(data=data) == pformat(data)

  def test_random(self):
    tmpl = env.from_string("""{{ seq|random }}""")
    seq = range(100)
    for _ in range(10):
      assert int(tmpl.render(seq=seq)) in seq

  def test_reverse(self):
    tmpl = env.from_string(
      '{{ "foobar"|reverse|join }}|' "{{ [1, 2, 3]|reverse|list }}"
    )
    assert tmpl.render() == "raboof|[3, 2, 1]"

  def test_string(self):
    x = [1, 2, 3, 4, 5]
    tmpl = env.from_string("""{{ obj|string }}""")
    assert tmpl.render(obj=x) == str(x)

  def test_title(self):
    tmpl = env.from_string("""{{ "foo bar"|title }}""")
    assert tmpl.render() == "Foo Bar"

  def test_truncate(self):
    tmpl = env.from_string(
      '{{ data|truncate(15, true, ">>>") }}|'
      '{{ data|truncate(15, false, ">>>") }}|'
      "{{ smalldata|truncate(15) }}"
    )
    out = tmpl.render(data="foobar baz bar" * 1000, smalldata="foobar baz bar")
    assert out == "foobar baz barf>>>|foobar baz >>>|foobar baz bar"

  def test_upper(self):
    tmpl = env.from_string('{{ "foo"|upper }}')
    assert tmpl.render() == "FOO"

  def test_urlize(self):
    tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
    assert (
      tmpl.render() == 'foo <a href="http://www.example.com/">'
      "http://www.example.com/</a> bar"
    )

  def test_wordcount(self):
    tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
    assert tmpl.render() == "3"

  def test_block(self):
    tmpl = env.from_string("{% filter lower|escape %}<HEHE>{% endfilter %}")
    assert tmpl.render() == "&lt;hehe&gt;"

  def test_chaining(self):
    tmpl = env.from_string("""{{ ['<foo>', '<bar>']|first|upper|escape }}""")
    assert tmpl.render() == "&lt;FOO&gt;"

  def test_sum(self):
    tmpl = env.from_string("""{{ [1, 2, 3, 4, 5, 6]|sum }}""")
    assert tmpl.render() == "21"

  def test_abs(self):
    tmpl = env.from_string("""{{ -1|abs }}|{{ 1|abs }}""")
    assert tmpl.render() == "1|1", tmpl.render()

  def test_round_positive(self):
    tmpl = env.from_string(
      "{{ 2.7|round }}|{{ 2.1|round }}|"
      "{{ 2.1234|round(3, 'floor') }}|"
      "{{ 2.1|round(0, 'ceil') }}"
    )
    assert tmpl.render() == "3.0|2.0|2.123|3.0", tmpl.render()

  def test_round_negative(self):
    tmpl = env.from_string(
      "{{ 21.3|round(-1)}}|"
      "{{ 21.3|round(-1, 'ceil')}}|"
      "{{ 21.3|round(-1, 'floor')}}"
    )
    assert tmpl.render() == "20.0|30.0|20.0", tmpl.render()

  def test_xmlattr(self):
    tmpl = env.from_string(
      "{{ {'foo': 42, 'bar': 23, 'fish': none, "
      "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}"
    )
    out = tmpl.render().split()
    assert len(out) == 3
    assert 'foo="42"' in out
    assert 'bar="23"' in out
    assert 'blub:blub="&lt;?&gt;"' in out

  def test_sort1(self):
    tmpl = env.from_string("{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}")
    assert tmpl.render() == "[1, 2, 3]|[3, 2, 1]"

  def test_sort2(self):
    tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort(false, true)) }}')
    assert tmpl.render() == "AbcD"

  def test_groupby(self):
    tmpl = env.from_string("""
        {%- for grouper, list in [{'foo': 1, 'bar': 2},
                                  {'foo': 2, 'bar': 3},
                                  {'foo': 1, 'bar': 1},
                                  {'foo': 3, 'bar': 4}]|groupby('foo') -%}
            {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
        {%- endfor %}""")
    assert tmpl.render().split("|") == ["1: 1, 2: 1, 1", "2: 2, 3", "3: 3, 4", ""]

  def test_filtertag(self):
    tmpl = env.from_string(
      "{% filter upper|replace('FOO', 'foo') %}" "foobar{% endfilter %}"
    )
    assert tmpl.render() == "fooBAR"

  def test_replace(self):
    env = Environment()
    tmpl = env.from_string('{{ string|replace("o", 42) }}')
    assert tmpl.render(string="<foo>") == "<f4242>"
    env = Environment(autoescape=True)
    tmpl = env.from_string('{{ string|replace("o", 42) }}')
    assert tmpl.render(string="<foo>") == "&lt;f4242&gt;"
    tmpl = env.from_string('{{ string|replace("<", 42) }}')
    assert tmpl.render(string="<foo>") == "42foo&gt;"
    tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
    assert tmpl.render(string=Markup("foo")) == "f&gt;x&lt;&gt;x&lt;"

  def test_forceescape(self):
    tmpl = env.from_string("{{ x|forceescape }}")
    assert tmpl.render(x=Markup("<div />")) == "&lt;div /&gt;"

  def test_safe(self):
    env = Environment(autoescape=True)
    tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
    assert tmpl.render() == "<div>foo</div>"
    tmpl = env.from_string('{{ "<div>foo</div>" }}')
    assert tmpl.render() == "&lt;div&gt;foo&lt;/div&gt;"

  def test_sort2(self):
    tmpl = env.from_string("""{{ ['foo', 'Bar', 'blah']|sort }}""")
    assert tmpl.render() == "['Bar', 'blah', 'foo']"


def suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(FilterTestCase))
  return suite
